#include <type.h>
#include "process.h"

struct alarm_info {
	time_t	time;
	int	pid;
	struct alarm_info *next;
};
#define NUM_ALARM_INFO 20
static struct alarm_info alarm_info_array[NUM_ALARM_INFO];
static struct alarm_info *alarm_head;
static time_t timer;

void init_clock(void)
{
	alarm_head = &alarm_info_array[0];
	alarm_head->next = NULL;
}

time_t gettime(void)
{
	return timer;
}

void alarm(time_t at)
{
	struct alarm_info *ai, *p;
	int i;

	/* Just pause. */
	if(at == 0)
		goto out;

	/* Add alarm. */
	/* malloc() */
	for(i = 1; i < NUM_ALARM_INFO; i++) {
		if(alarm_info_array[i].time == 0)
			break;
	}
	ai = &alarm_info_array[i];
	ai->time = timer + at;
	ai->pid = current->pid;

	/* Insert into the list. */
	for(p = alarm_head; p->next != NULL; p = p->next) {
		if(ai->time < p->next->time)
			break;
	}
	ai->next = p->next;
	p->next = ai;

out:
	/* Pause. */
	pause();
}

/* Remove the first block_info , so need not argment.
 * Return the new first alarm info. */
static struct alarm_info *rm_alarm(void)
{
	alarm_head->next->time = 0;
	alarm_head->next = alarm_head->next->next;
	return alarm_head->next;
}

/* Clock interupt handle. */
void clock_int_handle(void)
{
	struct alarm_info *p = alarm_head->next;

	timer++;

	while(p && (p->time <= timer)) {
		wake_up(p->pid);
		p = rm_alarm();
	}

	schedular();
}
